package org.jeecg.modules.system.util;

import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @program: recruit-boot-parent
 *
 * @author: JD
 * @create: 2020-08-28 10:31
 **/
public class ChineseUtil<T> {

    /**
     * 获取姓名全拼和首字母
     *
     * @param chinese 汉语名称
     * @return fullPinyin : 全拼        simplePinyin ： 首字母  groudPinyin：微信用户组第一个字母
     * @throws BadHanyuPinyinOutputFormatCombination
     * @author 于公成
     */
    public static Map<String, String> changeChinesePinyin(String chinese) throws BadHanyuPinyinOutputFormatCombination {
        Map<String, String> pinyin = new HashMap<>(16);

        HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
        format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
        format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
        format.setVCharType(HanyuPinyinVCharType.WITH_V);

        StringBuffer fullPinyin = new StringBuffer();
        StringBuffer simplePinyin = new StringBuffer();
        StringBuffer firstPinyin = new StringBuffer();

        char[] chineseChar = chinese.toCharArray();
        for (int i = 0; i < chineseChar.length; i++) {
            String[] str = null;
            try {
                str = PinyinHelper.toHanyuPinyinStringArray(chineseChar[i],
                        format);
            } catch (BadHanyuPinyinOutputFormatCombination e) {
                e.printStackTrace();
            }
            if (str != null && str.length > 0) {
                fullPinyin = fullPinyin.append(str[0]);
                simplePinyin = simplePinyin.append(str[0].charAt(0));

            }
            if (str == null) {
                String regex = "^[0-9]*[a-zA-Z]*+$";
                Pattern pattern = Pattern.compile(regex);
                Matcher m = pattern.matcher(String.valueOf(chineseChar[i]));
                if (m.find()) {
                    fullPinyin = fullPinyin.append(chineseChar[i]);
                    simplePinyin = simplePinyin.append(chineseChar[i]);
                }
            }
        }
        String[] name = PinyinHelper.toHanyuPinyinStringArray(chineseChar[0], format);
        if (name != null && name.length > 0) {
            firstPinyin = firstPinyin.append(name[0].charAt(0));
            pinyin.put("fullPinyin", fullPinyin.toString());
            pinyin.put("simplePinyin", simplePinyin.toString().toUpperCase());
            pinyin.put("groudPinyin", firstPinyin.toString().toUpperCase());

        } else {
            pinyin.put("fullPinyin", chinese);
            pinyin.put("simplePinyin", chinese);
            pinyin.put("groudPinyin", chinese);
        }
        return pinyin;
    }

    /**
     * 按用户拼音首字母分组
     *
     * @param list
     * @return
     * @throws BadHanyuPinyinOutputFormatCombination
     */
    public Map<String, List<T>> getUserCodeGroup(List list, String methodName) throws BadHanyuPinyinOutputFormatCombination, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //按字母排序
        Collections.sort(list);
        //输出26个字母
        Map<String, List<T>> map = new TreeMap<>();
        int count = 26;
        for (int i = 1; i <= count; i++) {
            String word = String.valueOf((char) (96 + i)).toUpperCase();
            //循环找出首字母一样的数据
            List<T> letter = new ArrayList<>();
            for (Object item : list) {
                Method method = item.getClass().getMethod(methodName);
                method.setAccessible(true);
                String str = (String) method.invoke(item);
                String code = changeChinesePinyin(str).get("groudPinyin");
                if (word.equals(code)) {
                    letter.add((T) item);
                }
            }
            map.put(word, letter);
        }
        return map;
    }
}
